#ifndef WAL_MANAGER_H
#define WAL_MANAGER_H

#include "../../include/gudb.h"
#include "../transaction/transaction_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include <time.h>

// WAL record types
typedef enum {
    WAL_INVALID = 0,
    WAL_INSERT,             // Insert operation
    WAL_UPDATE,             // Update operation  
    WAL_DELETE,             // Delete operation
    WAL_TRANSACTION_BEGIN,  // Transaction start
    WAL_TRANSACTION_COMMIT, // Transaction commit
    WAL_TRANSACTION_ABORT,  // Transaction abort
    WAL_CHECKPOINT,         // Checkpoint record
    WAL_PAGE_SPLIT,         // B-tree page split
    WAL_PAGE_MERGE,         // B-tree page merge
    WAL_CREATE_TABLE,       // DDL: Create table
    WAL_DROP_TABLE,         // DDL: Drop table
    WAL_CREATE_INDEX,       // DDL: Create index
    WAL_DROP_INDEX,         // DDL: Drop index
    WAL_VACUUM,             // Vacuum operation
    WAL_BACKUP_START,       // Backup start marker
    WAL_BACKUP_END          // Backup end marker
} wal_record_type_t;

// Log Sequence Number (LSN) - uniquely identifies each WAL record
typedef uint64_t lsn_t;

// Special LSN values
#define INVALID_LSN         0
#define BOOTSTRAP_LSN       1
#define MAX_LSN             UINT64_MAX

// WAL configuration constants
#define WAL_SEGMENT_SIZE    (16 * 1024 * 1024)  // 16MB per segment
#define WAL_BUFFER_SIZE     (1024 * 1024)       // 1MB buffer
#define WAL_MAX_RECORD_SIZE (64 * 1024)         // 64KB max record
#define WAL_SYNC_INTERVAL   1000                // Sync every 1000ms
#define WAL_CHECKPOINT_INTERVAL 300             // Checkpoint every 5 minutes

// Forward declarations
typedef struct wal_manager wal_manager_t;
typedef struct wal_record wal_record_t;
typedef struct wal_buffer wal_buffer_t;
typedef struct wal_segment wal_segment_t;
typedef struct checkpoint_info checkpoint_info_t;

// WAL record header - fixed size for all records
typedef struct {
    wal_record_type_t type;     // Record type
    uint32_t length;            // Total record length including header
    lsn_t lsn;                  // Log sequence number
    txn_id_t xid;              // Transaction ID
    timestamp_t timestamp;      // When record was created
    uint32_t crc32;            // CRC32 checksum
    lsn_t prev_lsn;            // Previous LSN for same transaction
} wal_record_header_t;

// WAL record structure
struct wal_record {
    wal_record_header_t header; // Fixed header
    void* data;                 // Variable-length data
    uint32_t data_size;         // Size of data
    
    // Buffer management
    bool is_allocated;          // Whether data is dynamically allocated
    struct wal_record* next;    // For free list
};

// Table operation data (for INSERT/UPDATE/DELETE)
typedef struct {
    uint32_t table_id;          // Table identifier
    uint32_t page_id;           // Page identifier
    uint64_t tuple_id;          // Tuple identifier
    uint32_t old_data_size;     // Size of old tuple data
    uint32_t new_data_size;     // Size of new tuple data
    // Followed by old_data and new_data
} wal_table_op_data_t;

// Transaction operation data
typedef struct {
    txn_id_t xid;              // Transaction ID
    isolation_level_t isolation; // Isolation level
    timestamp_t start_time;     // Transaction start time
} wal_txn_op_data_t;

// Checkpoint data  
typedef struct {
    lsn_t checkpoint_lsn;       // LSN of this checkpoint
    lsn_t redo_lsn;            // Oldest LSN that may need redo
    uint32_t active_txn_count;  // Number of active transactions
    // Followed by array of active transaction IDs
} wal_checkpoint_data_t;

// WAL buffer for batching writes
struct wal_buffer {
    char* data;                 // Buffer data
    uint32_t size;              // Buffer size
    uint32_t used;              // Bytes used
    uint32_t capacity;          // Buffer capacity
    
    pthread_mutex_t mutex;      // Protects buffer
    pthread_cond_t not_full;    // Signaled when buffer has space
    pthread_cond_t not_empty;   // Signaled when buffer has data
    
    bool flush_requested;       // Whether flush is requested
    lsn_t flush_lsn;           // LSN to flush up to
};

// WAL segment file
struct wal_segment {
    uint32_t segment_id;        // Segment number
    char* filename;             // Segment file path
    int fd;                     // File descriptor
    uint64_t size;              // Current segment size
    lsn_t start_lsn;           // First LSN in segment
    lsn_t end_lsn;             // Last LSN in segment
    
    bool is_active;             // Whether this is the active segment
    bool needs_sync;            // Whether segment needs fsync
    
    struct wal_segment* next;   // Next segment in list
};

// Checkpoint information
struct checkpoint_info {
    lsn_t checkpoint_lsn;       // LSN of last checkpoint
    lsn_t redo_lsn;            // Oldest LSN needed for recovery
    timestamp_t checkpoint_time; // When checkpoint was taken
    uint32_t segments_before;   // Segments before checkpoint
    char* checkpoint_filename;  // Checkpoint metadata file
};

// WAL manager - coordinates all WAL operations
struct wal_manager {
    // Configuration
    char* wal_directory;        // WAL files directory
    uint32_t segment_size;      // Size of each segment
    uint32_t buffer_size;       // Size of WAL buffer
    uint32_t sync_interval_ms;  // Sync interval in milliseconds
    uint32_t checkpoint_interval_sec; // Checkpoint interval in seconds
    
    // LSN management
    lsn_t next_lsn;            // Next LSN to assign
    lsn_t flushed_lsn;         // Last LSN flushed to disk
    lsn_t checkpoint_lsn;      // Last checkpoint LSN
    pthread_mutex_t lsn_mutex; // Protects LSN counters
    
    // Segments
    wal_segment_t* segments;    // List of segments
    wal_segment_t* active_segment; // Currently active segment
    uint32_t next_segment_id;   // Next segment ID
    pthread_rwlock_t segments_lock; // Protects segment list
    
    // Buffer
    wal_buffer_t* buffer;       // WAL buffer
    
    // Background threads
    pthread_t writer_thread;    // Background writer
    pthread_t checkpoint_thread; // Checkpoint thread
    bool threads_running;       // Whether threads should run
    
    // Synchronization
    pthread_mutex_t flush_mutex; // Protects flush operations
    pthread_cond_t flush_cond;  // Signaled when flush completes
    
    // Statistics
    uint64_t records_written;   // Total records written
    uint64_t bytes_written;     // Total bytes written
    uint64_t syncs_performed;   // Number of syncs
    uint64_t checkpoints_taken; // Number of checkpoints
    uint64_t segments_created;  // Number of segments created
    
    // Recovery state
    bool in_recovery;           // Whether we're in recovery mode
    lsn_t recovery_start_lsn;   // LSN to start recovery from
    lsn_t recovery_end_lsn;     // LSN to end recovery at
    
    // Checkpoint info
    checkpoint_info_t* last_checkpoint; // Last checkpoint taken
};

// WAL Manager API

// Lifecycle management
wal_manager_t* wal_manager_create(const char* wal_directory);
void wal_manager_destroy(wal_manager_t* wal);
int wal_manager_start(wal_manager_t* wal);
int wal_manager_stop(wal_manager_t* wal);

// Configuration
int wal_set_segment_size(wal_manager_t* wal, uint32_t size);
int wal_set_buffer_size(wal_manager_t* wal, uint32_t size);
int wal_set_sync_interval(wal_manager_t* wal, uint32_t interval_ms);
int wal_set_checkpoint_interval(wal_manager_t* wal, uint32_t interval_sec);

// Record operations
lsn_t wal_insert_record(wal_manager_t* wal, wal_record_type_t type, 
                       txn_id_t xid, const void* data, uint32_t data_size);
lsn_t wal_log_insert(wal_manager_t* wal, txn_id_t xid, uint32_t table_id,
                     uint32_t page_id, uint64_t tuple_id, 
                     const void* tuple_data, uint32_t data_size);
lsn_t wal_log_update(wal_manager_t* wal, txn_id_t xid, uint32_t table_id,
                     uint32_t page_id, uint64_t tuple_id,
                     const void* old_data, uint32_t old_size,
                     const void* new_data, uint32_t new_size);
lsn_t wal_log_delete(wal_manager_t* wal, txn_id_t xid, uint32_t table_id,
                     uint32_t page_id, uint64_t tuple_id,
                     const void* tuple_data, uint32_t data_size);
lsn_t wal_log_transaction_begin(wal_manager_t* wal, txn_id_t xid, 
                               isolation_level_t isolation);
lsn_t wal_log_transaction_commit(wal_manager_t* wal, txn_id_t xid);
lsn_t wal_log_transaction_abort(wal_manager_t* wal, txn_id_t xid);

// Flush and sync operations
int wal_flush_to_lsn(wal_manager_t* wal, lsn_t lsn);
int wal_sync_to_lsn(wal_manager_t* wal, lsn_t lsn);
int wal_force_sync(wal_manager_t* wal);

// Checkpoint operations
lsn_t wal_create_checkpoint(wal_manager_t* wal, txn_id_t* active_xids, 
                           uint32_t active_count);
int wal_restore_checkpoint(wal_manager_t* wal, checkpoint_info_t** checkpoint);

// Recovery operations
int wal_start_recovery(wal_manager_t* wal);
int wal_get_next_record(wal_manager_t* wal, wal_record_t** record);
int wal_apply_record(wal_manager_t* wal, wal_record_t* record);
int wal_finish_recovery(wal_manager_t* wal);

// Segment management
wal_segment_t* wal_create_segment(wal_manager_t* wal);
int wal_close_segment(wal_manager_t* wal, wal_segment_t* segment);
int wal_remove_old_segments(wal_manager_t* wal, lsn_t oldest_needed_lsn);

// Record management
wal_record_t* wal_record_create(wal_record_type_t type, txn_id_t xid,
                               const void* data, uint32_t data_size);
void wal_record_destroy(wal_record_t* record);
wal_record_t* wal_record_read(wal_manager_t* wal, lsn_t lsn);

// Buffer management
wal_buffer_t* wal_buffer_create(uint32_t capacity);
void wal_buffer_destroy(wal_buffer_t* buffer);
int wal_buffer_append(wal_buffer_t* buffer, wal_record_t* record);
int wal_buffer_flush(wal_manager_t* wal, wal_buffer_t* buffer);

// Utility functions
uint32_t wal_calculate_crc32(const void* data, uint32_t size);
bool wal_verify_record(wal_record_t* record);
lsn_t wal_get_current_lsn(wal_manager_t* wal);
lsn_t wal_get_flushed_lsn(wal_manager_t* wal);

// Statistics and monitoring
void wal_print_stats(wal_manager_t* wal);
int wal_get_segment_count(wal_manager_t* wal);
uint64_t wal_get_total_size(wal_manager_t* wal);

// String conversion functions
const char* wal_record_type_to_string(wal_record_type_t type);

// Background thread functions (internal)
void* wal_writer_thread_func(void* arg);
void* wal_checkpoint_thread_func(void* arg);

// Internal helper functions
static lsn_t assign_lsn(wal_manager_t* wal);
static int write_record_to_segment(wal_manager_t* wal, wal_segment_t* segment, 
                                  wal_record_t* record);
static wal_record_t* read_record_from_segment(wal_segment_t* segment, 
                                             uint64_t offset);

#endif // WAL_MANAGER_H